package com.xtaller.lazy.base;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xtaller.lazy.lib.annotation.Table;
import com.xtaller.lazy.lib.convert.J;
import com.xtaller.lazy.lib.convert.S;
import com.xtaller.lazy.lib.kit.IdUtil;
import com.xtaller.lazy.lib.kit.TimeUtil;
import lombok.var;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*;

/**
 * @version V1.0
 * @author: Taller
 * @date: 2019-04-02
 * @Description:
 */
public class TServiceImpl<M extends BaseMapper<T>, T> extends ServiceImpl<M, T> {
    private final String PK_ID = "id";
    private final String CREATE_TIME = "createTime";
    private Class<T> clz;
    List logs = Arrays.asList(162, 163);
    /**
     * 数据创建或修改 返回实体
     * */
    public T model(T entity){
        JSONObject object = J.o2j(entity);
        boolean success = false;
        var id = 0L;
        if (object.get(PK_ID) == null
                || object.get(PK_ID).equals(0)
                || object.get(PK_ID).equals(0L)
                || object.get(PK_ID).equals("")){
            var t = insertEntity(entity);
            JSONObject tem = J.o2j(t);
            success = save(t);
            id = tem.getLong(PK_ID);
        }else {
            var t = updateEntity(entity);
            JSONObject tem = J.o2j(t);
            success = updateById(t);
            id = tem.getLong(PK_ID);
        }
        var tableId = entity.getClass().getAnnotation(Table.class).id();
        if(success) {
            // 记录非日志类数据
            entity = getById(id);
            if(!logs.contains(tableId)){
                object.remove("createTime");
                object.remove("updateTime");
                object.remove("version");
                object.remove("revision");
                System.err.println(J.o2s(object));
            }
            return entity;
        }
        return null;
    }

    /**********************************创建******************************************/
    @Override
    public boolean save(T entity) {
        return super.save(insertEntity(entity));
    }

    @Override
    public boolean saveBatch(Collection<T> entityList, int batchSize){
        Collection<T> tem = new ArrayList<>();
        // 数据处理
        for(var entity : entityList){
            entity = insertEntity(entity);
            tem.add(entity);
        }
        return super.saveBatch(tem, batchSize);
    }
    /**
     * 物理删除
     * */
    public boolean delete(Wrapper<T> wrapper) {
        return super.remove(wrapper);
    }

    /**********************************创建/编辑**************************************/
    @Override
    public boolean saveOrUpdate(T entity){
        return super.saveOrUpdate(insertEntity(entity));
    }
    @Override
    public boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize){
        Collection<T> tem = new ArrayList<>();
        // 数据处理
        for(var entity : entityList){
            entity = insertEntity(entity);
            tem.add(entity);
        }
        return super.saveOrUpdateBatch(tem, batchSize);
    }

    /***********************************删除*****************************************/
    @Override
    public boolean remove(Wrapper<T> wrapper) {
        return super.update(deleteEntity(), wrapper);
    }
    @Override
    public boolean removeById(Serializable id) {
        QueryWrapper<T> where = new QueryWrapper<>();
        where.eq(PK_ID, id);
        where.eq("isDelete", 0);
        return super.update(deleteEntity(), where);
    }
    @Override
    public boolean removeByIds(Collection<? extends Serializable> idList) {
        QueryWrapper<T> where = new QueryWrapper<>();
        where.in(PK_ID, idList);
        return super.update(deleteEntity(), where);
    }

    /***********************************编辑****************************************/
    @Override
    public boolean updateById(T entity){
        var obj = J.o2j(entity);
        QueryWrapper<T> ew = new QueryWrapper<>();
        ew.eq(PK_ID, obj.get(PK_ID));
        ew.eq("isDelete", 0);
        return super.update(updateEntity(entity), ew);
    }
    @Override
    public boolean update(T entity, Wrapper<T> wrapper){
        return super.update(updateEntity(entity), wrapper);
    }
    @Override
    public boolean updateBatchById(Collection<T> entityList, int batchSize){
        Collection<T> tem = new ArrayList<>();
        // 数据处理
        for(var entity : entityList){
            entity = insertEntity(entity);
            tem.add(entity);
        }
        return super.updateBatchById(tem, batchSize);
    }

    /***********************************查询****************************************/
    @Override
    public T getById(Serializable id) {
        QueryWrapper<T> where = new QueryWrapper<>();
        where.eq(PK_ID, id);
        where.eq("isDelete", 0);
        return super.getOne(where);
    }
    @Override
    public List<T> listByIds(Collection<? extends Serializable> idList){
        QueryWrapper<T> where = new QueryWrapper<>();
        where.in(PK_ID, idList);
        where.eq("isDelete", 0);
        return super.list(where);
    }
    @Override
    public List<T> listByMap(Map<String, Object> columnMap){
        columnMap.put("isDelete", 0);
        return (List<T>) super.listByMap(columnMap);
    }
    @Override
    public T getOne(Wrapper<T> qw, boolean throwEx) {
        QueryWrapper<T> where = (QueryWrapper<T>) qw;
        where.eq("isDelete", 0);
        return super.getOne(where, throwEx);
    }
    @Override
    public Map<String, Object> getMap(Wrapper<T> qw) {
        QueryWrapper<T> where = (QueryWrapper<T>) qw;
        where.eq("isDelete", 0);
        return super.getMap(where);
    }
    @Override
    public int count(Wrapper<T> qw){
        QueryWrapper<T> where = (QueryWrapper<T>) qw;
        where.eq("isDelete", 0);
        return super.count(where);
    }
    @Override
    public List<T> list(Wrapper<T> qw) {
        QueryWrapper<T> where = (QueryWrapper<T>) qw;
        where.eq("isDelete", 0);
        return super.list(where);
    }

    @Override
    public List<T> list() {
        QueryWrapper<T> where = new QueryWrapper<>();
        where.eq("isDelete", 0);
        return super.list(where);
    }

    @Override
    public IPage<T> page(IPage<T> page, Wrapper<T> qw) {
        QueryWrapper<T> where = (QueryWrapper<T>) qw;
        where.eq("isDelete", 0);
        return super.page(page, where);
    }
    @Override
    public IPage<T> page(IPage<T> page) {
        QueryWrapper<T> where = new QueryWrapper<>();
        where.eq("isDelete", 0);
        return super.page(page, where);
    }

    @Override
    public List<Map<String, Object>> listMaps(Wrapper<T> qw) {
        QueryWrapper<T> where = (QueryWrapper<T>) qw;
        where.eq("isDelete", 0);
        return super.listMaps(where);
    }
    @Override
    public IPage<Map<String, Object>> pageMaps(IPage<T> page, Wrapper<T> qw) {
        QueryWrapper<T> where = (QueryWrapper<T>) qw;
        where.eq("isDelete", 0);
        return super.pageMaps(page, where);
    }




    /**
     * 实体数据处理
     * */
    private T insertEntity(T entity){
        JSONObject object = J.o2j(entity);
        int vt = TimeUtil.getTimestamp();
        // 全局id
        var table = entity.getClass().getAnnotation(Table.class);
        if (object.get(PK_ID) == null || object.get(PK_ID).equals(0) || object.get(PK_ID).equals("")) {
            object.put(PK_ID, IdUtil.getLongId(table.id()));
            if(object.get(CREATE_TIME) == null || object.get(CREATE_TIME).equals(0) || object.get(CREATE_TIME).equals("")){
                object.put(CREATE_TIME, vt);
            }
            
            object.put("uuid", S.uuid());
        }else{
            object.put("updateTime", vt);
        }
        // 乐观锁判断
        if (this.checkLock(entity)) {
            object.put("version", vt);
        }
        return JSON.parseObject(J.o2s(object), (Type) entity.getClass());
    }
    private T updateEntity(T entity){
        JSONObject object = J.o2j(entity);
        int vt = TimeUtil.getTimestamp();
        // 乐观锁判断
        if (this.checkLock(entity)) {
            object.put("version", vt);
        }
        object.put("updateTime", vt);
        return JSON.parseObject(J.o2s(object), (Type) entity.getClass());
    }
    private T deleteEntity(){
        JSONObject object = new JSONObject();

        int vt = TimeUtil.getTimestamp();
        object.put("isDelete", 1);

        object.put("updateTime", vt);
        return JSON.parseObject(J.o2s(object), (Type) getRealType());
    }

    // 检查是否开启乐观锁
    private boolean checkLock(T t) {
        boolean check = false;
        Field[] fields = t.getClass().getDeclaredFields();

        for(int j = 0; j < fields.length; ++j) {
            String name = fields[j].getName().toLowerCase();
            if (name.equals("version")) {
                check = true;
                break;
            }
        }
        return check;
    }

    // 使用反射技术得到T的真实类型
    public Class getRealType(){
        // 获取当前new的对象的泛型的父类类型
        ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();
        // 获取第2个类型参数的真实类型
        this.clz = (Class<T>) pt.getActualTypeArguments()[1];
        return clz;
    }

}
